'use strict'

process.chdir(__dirname)

const cluster = require('cluster')

const initconfig = require('./initconfig.js')

cluster.isMaster && initconfig()

const fs = require('fs')
const Titbit = require('titbit')
const tbloader = require('titbit-loader')
const {resource, mixlogger} = require('titbit-toolkit')
const {initORM} = require('psqlorm')
const config = require('./config/config.js')
const database = require('./config/database.js')
const funcs = require('./lib/funcs.js')
const cdpc = require('cdpc')
const npargv = require('npargv')
const TitbitToken = require('titbit-token')
const sm4password = require('sm4-password')

const fsp = fs.promises

const {args} = npargv({
  '--test' : {
    name: 'test',
    default: false,
  },

  '--debug' : {
    name: 'debug',
    default: false,
  },
})

let loadfile = '/tmp/nodeapp-load.log'

if (process.platform.indexOf('win') === 0) {
  loadfile = __dirname + '/tmp/nodeapp-load.log'
}

const app = new Titbit({
  debug: args.debug,
  maxUrlLength: 4096,
  maxQuery: 50,
  monitorTimeSlice: 200,
  //loadInfoFile: loadfile,
  loadInfoFile: '--mem',
  loadInfoType: 'json',
  https: config.https,
  http2: config.http2,
  allowHTTP1: config.allowHTTP1,
  cert: (config.https || config.http2 )? config.cert : '',
  key: (config.https || config.http2 )? config.key : '',
  server: {
    handshakeTimeout: 10000
  },
  maxLoadRate: 75,

  //启用全局日志
  globalLog: true,

  logType: 'file',
  logFile: './tmp/success.log',
  errorLogFile: './tmp/error.log',
  
  //日志文件最大条数
  logMaxLines: 10000,

  //最大历史日志文件数量
  logHistory: 50
})

if (app.isMaster) {
  ;(new mixlogger({
    logHandle: (w, msg, handle) => {
      if (msg.log.indexOf('/sys/loadinfo', 7) > 0) {
        return false
      }
    
      return true
    }
  })).init(app)

  try {
    fs.accessSync(__dirname + '/tmp')
  } catch (err) {
    fs.mkdirSync(__dirname + '/tmp')
  }

  ;[
    '/storage', 
    '/storage/images',
    '/storage/audios',
    '/storage/videos',
    '/storage/files'
  ].forEach(a => {
    funcs.tryMkdir(__dirname + a).catch(err => {
      console.error(err)
    })
  })
}

if (config.autoWorker > 0 && config.autoWorker > config.worker) {
  app.autoWorker(config.autoWorker)
}

if (app.isWorker) {
  let pqorm = initORM(database.connect, database.schema)

  app.addService('loadfile', loadfile)
  app.addService('DEBUG', args.debug)
  app.addService('TEST', args.test)

  app.addService('appDir', __dirname)
  app.addService('storageDir', `${__dirname}/storage`)

  app.addService('pqorm', pqorm)
  app.addService('config', config)
  app.addService('funcs', funcs)

  let tbl = new tbloader({
    mdb: pqorm
  })
  
  tbl.init(app)

  //初始化静态资源
  let rse = new resource({
    staticPath: `${__dirname}/public/static`,
    routePath : '/static/*',
    routeGroup: '_static',
    decodePath: true,
  })
  
  rse.init(app)

  app.get('/favicon.ico', async c => {}, {group: '_static'})
  
  app.get('/', async c => {
    await c.helper.pipe('./public/index.html', c.reply)
  })

  //开发测试环境下，用于前端展示路由表和相关提示信息
  if (args.debug || args.test) {
    /* app.get('/dev', async c => {
      try {
        await c.helper.pipe('./public/dev.hmtl', c.reply)
      } catch (err) {
        c.status(404).send(`<!DOCTYPE>
          <html>
            <head></head>
            <body>
              <div style="font-weight:bold;font-size:125%;">未找到页面</div>
            </body>
          </html>`
        )
      }
    })

    app.get('/dev/routes', async c => {

    }) */
  }
  
  app.get('/page/:name', async c => {
    try {
      await c.helper.pipe( `./public/${c.param.name}.html`, c.reply)
    } catch (err) {
      c.service.DEBUG && console.error(err)
      c.status(404)
      await c.helper.pipe( `./public/errorpages/404.html`, c.reply)
    }
  })

  //用于amdin分组的token验证
  let atok = new TitbitToken({
    iv: config.admin.iv || '1qaz2wsx3edc4rfv',
    key: config.admin.key,
    expires: config.admin.expires > 0 ? config.admin.expires : 3600000
  })

  app.addService('atok', atok)

  //用于api分组的token验证
  let tok = new TitbitToken({
    iv: config.api.iv || '4rfv5tgb6yhn7ujm',
    key: config.api.key,
    expires: config.api.expires > 0 ? config.api.expires : 3600000
  })

  app.addService('tok', tok)

  app.addService('upass', new sm4password())
}

//设定负载消息传递
if (app.isWorker) {
  app.workerMsg(msg => {
    if (msg.type === 'loadinfo') {
      global.__loadinfo__ = msg.data
    }
  })
} else {
  app.setMsgEvent('loadinfo', (wk, msg) => {
    wk.send({
      type: 'loadinfo',
      data: app.monitor.loadCache
    })
  })
}

let port = 1234

if (app.isWorker) {
  app.send('loadinfo', {})
  app.addService('loadinfo', () => {
    app.send('loadinfo', {})
  })

  //设置service
  fsp.access('./config/service.js')
    .then(res => {
      let service = require('./config/service.js')
      for (let k in service) {
        if (app.service[k]) {
          console.error(`app.service: ${k}已经存在，配置冲突`)
        } else {
          app.service[k] = service[k]
        }
      }
    })
    .catch(err => {})
}

app.daemon(config.port || port, config.host || '::', config.worker)
